package com.wawu.handle;


import com.wawu.annotation.controller.Mapping.GetMapping;
import com.wawu.annotation.controller.Mapping.PostMapping;
import com.wawu.annotation.controller.Mapping.RequestMapping;
import com.wawu.annotation.parameter.RequestBody;
import com.wawu.annotation.parameter.RequestParam;
import com.wawu.enumeration.RequestMethodEnum;
import com.wawu.ioc.ApplicationContext;
import com.wawu.property.TomcatProperty;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;

import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.Map;




public class AopRequestHandler {

    private static final Map<String, Method> routes = new HashMap<>();
    private static final Map<String, Object> controllers = new HashMap<>(); // 路由对应控制器实例

    public static void initializeRoutes(ApplicationContext context) {
        // 获取所有RestController及其方法
        for (Class<?> restcontrollerClass : context.getRestControllerClazzes()) {
            Object restController = context.getBean(restcontrollerClass);
            String basePath = "";
            if (restcontrollerClass.isAnnotationPresent(RequestMapping.class)) {
                basePath = restcontrollerClass.getAnnotation(RequestMapping.class).value()[0];
            }

            for (Method method : restcontrollerClass.getDeclaredMethods()) {
                String methodPath = ""; // 方法的路径，默认空

                if (method.isAnnotationPresent(GetMapping.class)) {
                    methodPath = method.getAnnotation(GetMapping.class).value()[0];
                    registerRoute(basePath, methodPath, RequestMethodEnum.GET, method, restController);
                } else if (method.isAnnotationPresent(PostMapping.class)) {
                    methodPath = method.getAnnotation(PostMapping.class).value()[0];
                    registerRoute(basePath, methodPath, RequestMethodEnum.POST, method, restController);
                } // 继续为 PUT、DELETE 等方法添加处理
            }
        }
        System.out.println("注册的路由有："+routes);
        System.out.println("注册的控制类："+controllers);
    }

    private static void registerRoute(String basePath, String methodPath, RequestMethodEnum methodEnum, Method method, Object controller) {
        String fullPath = (basePath + methodPath).replaceAll("/+", "/");
        routes.put(methodEnum.name() + fullPath, method);
        controllers.put(methodEnum.name() + fullPath, controller); // 记录控制器实例
    }

    public static void handleRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String httpMethod = request.getMethod();
        String relativePath = request.getRequestURI().substring(TomcatProperty.CONTEXT_PATH.length());
        String routeKey = httpMethod + relativePath;

        Method handlerMethod = routes.get(routeKey);
        Object controller = controllers.get(routeKey);

        System.out.println("Handler Method: " + handlerMethod);
        System.out.println("Requested Method and Path: " + httpMethod + " " + relativePath);

        if (handlerMethod != null && controller != null) {
            try {
                handlerMethod.setAccessible(true);
                Object[] args = resolveMethodParameters(handlerMethod, request);
                Object result = handlerMethod.invoke(controller, args);

                // JSON 响应处理
                String jsonResponse = JSONObject.toJSONString(result);
                response.setContentType("application/json");
                response.setCharacterEncoding("UTF-8");
                response.getWriter().write(jsonResponse);
            } catch (Exception e) {
                e.printStackTrace();
                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error processing request");
            }
        } else {
            response.sendError(HttpServletResponse.SC_NOT_FOUND, "Route not found");
        }
    }

    // 辅助方法：解析方法参数(主要为的是解析请求体参数和请求体内容)
    private static Object[] resolveMethodParameters(Method method, HttpServletRequest request) throws IOException {
        Parameter[] parameters = method.getParameters();
        Object[] args = new Object[parameters.length];

        String requestBody = null;
        if ("POST".equalsIgnoreCase(request.getMethod()) || "PUT".equalsIgnoreCase(request.getMethod())) {
            requestBody = request.getReader().lines().reduce("", String::concat);
        }

        for (int i = 0; i < parameters.length; i++) {
            Parameter parameter = parameters[i];
            if (parameter.isAnnotationPresent(RequestBody.class)) {
                args[i] = JSON.parseObject(requestBody, parameter.getType());
            } else if (parameter.isAnnotationPresent(RequestParam.class)) {
                String paramName = parameter.getAnnotation(RequestParam.class).value();
                String paramValue = request.getParameter(paramName);
                args[i] = convertToType(paramValue, parameter.getType());
            } else {
                String paramValue = request.getParameter(parameter.getName());
                args[i] = convertToType(paramValue, parameter.getType());
            }
        }
        return args;
    }


    // 辅助方法：类型转换
    private static Object convertToType(String value, Class<?> type) {
        if (value == null) return null;
        if (type == Integer.class || type == int.class) {
            return Integer.parseInt(value);
        } else if (type == Double.class || type == double.class) {
            return Double.parseDouble(value);
        }
        return value;
    }
}


////TODO 这里部分注释还没有整理，上面那个注释不全
//////初版（没有带有IOC容器版本）////
////一开始是直接static{}静态变量初始化，但是这里将要你引入ApplicationContext注册的@Component来了
//import com.alibaba.fastjson2.JSON;
//import com.alibaba.fastjson2.JSONObject;
//import com.wawu.annotation.IOC.component.RestController;
//import com.wawu.annotation.controller.Mapping.*;
//import com.wawu.annotation.parameter.RequestBody;
//import com.wawu.annotation.parameter.RequestParam;
//import com.wawu.enumeration.RequestMethodEnum;
//import com.wawu.property.TomcatProperty;
//import jakarta.servlet.http.HttpServletRequest;
//import jakarta.servlet.http.HttpServletResponse;
//import org.reflections.Reflections;
//import org.reflections.scanners.Scanners;
//import org.reflections.util.ConfigurationBuilder;
//
//import java.io.IOException;
//import java.lang.reflect.Method;
//import java.lang.reflect.Parameter;
//import java.util.HashMap;
//import java.util.HashSet;
//import java.util.Map;
//import java.util.Set;
//
//
//public class AopRequestHandler {
//
//    private static final Map<String, Method> routes = new HashMap<>();
//
//    static {
//        try {
//            scanControllers("com.wawu.controller"); // 调整为你的包路径
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//    }
//
//    private static Set<Class<?>> getClassesInPackage(String packageName) {
//        //注意： 这里是会扫描整个子包
//        Reflections reflections = new Reflections(new ConfigurationBuilder()
//                .forPackages(packageName)//设置包名
//                .addScanners(Scanners.TypesAnnotated));//扫描带注解的类型
//
//
//        Set<Class<?>> controllers = new HashSet<>(reflections.getTypesAnnotatedWith(RestController.class));
//        System.out.println("当前控制层："+controllers);
//        return controllers;
//    }
//
//    //TODO 待解决，就是我这里其实就是定义了一个假拦截器（本质还是Servlet），但是这里竟然也会注册路径
//    //TODO 待优化：支持多路径、多请求方式，
//    //  这里先不整了，默认第一个
//    private static void scanControllers(String packageName) throws Exception {
//        for (Class<?> controller : getClassesInPackage(packageName)) {
//            // TODO 确保扫描的类属于指定的包
//            //  确保扫描的是controller层的，这样感觉不太行后面在细想一下
//            if (!controller.getPackage().getName().startsWith(packageName)) {
//                continue;
//            }
//
//            if (controller.isAnnotationPresent(RestController.class)) {
//                if (controller.isAnnotationPresent(RequestMapping.class)) {
//                    //遍历所有的父地址
//                    String basePath=controller.getAnnotation(RequestMapping.class).value()[0];
//
//                    // 遍历方法，获取每个方法的请求路径和请求方式
//                    for (Method method : controller.getDeclaredMethods()) {
//                        String methodPath =""; // 方法的路径，默认空
//
//                        // 检查方法上的各个请求方式注解（如 @GetMapping, @PostMapping）
//                        if (method.isAnnotationPresent(GetMapping.class)) {
//                            methodPath = method.getAnnotation(GetMapping.class).value()[0];
//                            registerMethodRoutes(basePath, methodPath, RequestMethodEnum.GET, method);
//                        } else if (method.isAnnotationPresent(PostMapping.class)) {
//                            methodPath = method.getAnnotation(PostMapping.class).value()[0];
//                            registerMethodRoutes(basePath, methodPath, RequestMethodEnum.POST, method);
//                        } else if (method.isAnnotationPresent(PutMapping.class)) {
//                            methodPath = method.getAnnotation(PutMapping.class).value()[0];
//                            registerMethodRoutes(basePath, methodPath, RequestMethodEnum.PUT, method);
//                        } else if (method.isAnnotationPresent(DeleteMapping.class)) {
//                            methodPath = method.getAnnotation(PutMapping.class).value()[0];
//                            registerMethodRoutes(basePath, methodPath, RequestMethodEnum.DELETE, method);
//                        }
//                    }
//
//                }
//            }
//        }
//        System.out.println("注测路由信息："+routes);
//
//    }
//    // 辅助方法：注册请求路径和方法映射
//    private static void registerMethodRoutes(String basePath, String methodPath, RequestMethodEnum methodEnum, Method method) {
//        String fullPath = basePath + methodPath;
//        fullPath = fullPath.replaceAll("/+", "/");  // 清理多余的斜杠
//        routes.put(methodEnum.name() + fullPath, method);
//    }
//
//    // 处理请求
//    public static void handleRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
//        String httpMethod = request.getMethod();
//        //这里是存在上下文环境的，就是tomcat中会进行单独配置，所以最好就是把这个放在配置文件中
//        //获取对应的处理类的路径
//            // 处理上下文路径为空的情况
//            //这时候访问：http://localhost:8083/api，上下文环境变为了"/api"
//            //如果在tomcat中配置了上下文是正常的
//        String relativePath = request.getRequestURI().substring(TomcatProperty.CONTEXT_PATH.length());
//        Method handlerMethod = routes.get(httpMethod + relativePath);
//        System.out.println("Handler Method: " + handlerMethod);
//        System.out.println("Requested Method and Path: " + httpMethod + " " + relativePath);
//
//        if (handlerMethod != null) {
//            try {
//                //调用方法，获取返回值
//                handlerMethod.setAccessible(true);
//                Object[] args = resolveMethodParameters(handlerMethod, request);
//                Object result = handlerMethod.invoke(handlerMethod.getDeclaringClass().newInstance(), args);
//                //将返回值，设置为json格式返回
//                String jsonResponse = JSONObject.toJSONString(result);
//                response.setContentType("application/json");
//                response.setCharacterEncoding("UTF-8");
//                response.getWriter().write(jsonResponse);
//            } catch (Exception e) {
//                e.printStackTrace();
//                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error processing request");
//            }
//        } else {
//            response.sendError(HttpServletResponse.SC_NOT_FOUND, "Route not found");
//        }
//    }
//
//    // 辅助方法：解析方法参数
//    private static Object[] resolveMethodParameters(Method method, HttpServletRequest request) throws IOException {
//        Parameter[] parameters = method.getParameters();
//        Object[] args = new Object[parameters.length];
//
//        String requestBody = null;
//        if ("POST".equalsIgnoreCase(request.getMethod()) || "PUT".equalsIgnoreCase(request.getMethod())) {
//            requestBody = request.getReader().lines().reduce("", String::concat);
//        }
//
//        for (int i = 0; i < parameters.length; i++) {
//            Parameter parameter = parameters[i];
//            if (parameter.isAnnotationPresent(RequestBody.class)) {
//                args[i] = JSON.parseObject(requestBody, parameter.getType());
//            } else if (parameter.isAnnotationPresent(RequestParam.class)) {
//                String paramName = parameter.getAnnotation(RequestParam.class).value();
//                String paramValue = request.getParameter(paramName);
//                args[i] = convertToType(paramValue, parameter.getType());
//            } else {
//                String paramValue = request.getParameter(parameter.getName());
//                args[i] = convertToType(paramValue, parameter.getType());
//            }
//        }
//        return args;
//    }
//
//    // 辅助方法：类型转换
//    private static Object convertToType(String value, Class<?> type) {
//        if (value == null) return null;
//        if (type == Integer.class || type == int.class) {
//            return Integer.parseInt(value);
//        } else if (type == Double.class || type == double.class) {
//            return Double.parseDouble(value);
//        }
//        return value;
//    }
//
//}
////结束////
